﻿using System.Reflection;

namespace LPLS.Commons.Mappers
{
    public class ReflectionMapper
    {
        public static TDestination Map<TSource, TDestination>(TSource source, TDestination destination)
        {
            if (destination == null)
            {
                destination = Activator.CreateInstance<TDestination>();
            }

            var sourceProperties = typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            var destinationProperties = typeof(TDestination).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            var destinationPropertyLookup = new Dictionary<string, PropertyInfo>();
            foreach (var property in destinationProperties)
            {
                destinationPropertyLookup[property.Name] = property;
            }

            foreach (var sourceProperty in sourceProperties)
            {
                if (destinationPropertyLookup.TryGetValue(sourceProperty.Name, out var destinationProperty))
                {
                    if (destinationProperty.PropertyType == sourceProperty.PropertyType && destinationProperty.CanWrite)
                    {
                        destinationProperty.SetValue(destination, sourceProperty.GetValue(source));
                    }
                }
            }

            return destination;
        }

        public static List<TDestination> MapList<TSource, TDestination>(List<TSource> sourceList)
        {
            var destinationList = new List<TDestination>();

            foreach (var source in sourceList)
            {
                var destination = Activator.CreateInstance<TDestination>();
                destination = Map(source, destination);
                destinationList.Add(destination);
            }

            return destinationList;
        }
    }
}
